/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	Tokenizer.cpp
*
*	Comments	-	See Tokenizer.h
*
**************************************************************************************/
#include "../Include/Tokenizer.h"

namespace Pulse
{
	BOOL Tokenizer::NextToken( const CHAR *pParametersInput, UPOS_T *pMarker, String *pTokenToStore )
	{
		if ( pParametersInput == PSX_NULL || pMarker == PSX_NULL || pTokenToStore == PSX_NULL )
			return FALSE;

		// The rule is that we stop everytime we hit a space or a null.
		// If we hit at the start, that means its the end
		// If we started with something valid then ended with one of the terminations, we have a valid token.

		CHAR currentChar = pParametersInput[*pMarker];

		if ( currentChar  == PSX_NULL )
			return FALSE;

		UPOS_T startMarker = *pMarker;
		UPOS_T endMarker = *pMarker;

		// We want to skip any inital spaces or null and set the startMarket from there
		while ( currentChar == PSX_String(' ') || currentChar == PSX_NULL )
		{
			// We can end up in null. So handle exit gracefully
			if ( currentChar == PSX_NULL )
			{
				return FALSE;
			}

			++startMarker;
			currentChar = pParametersInput[startMarker];
		}
		
		while ( currentChar != PSX_String(' ') && currentChar != PSX_NULL )
		{
			++endMarker;
			currentChar = pParametersInput[endMarker];
		}

		if ( startMarker == endMarker )
			return FALSE;

		// Create new token
		SIZE_T numToCopy = (endMarker - startMarker);
		pTokenToStore->Copy( &pParametersInput[startMarker], numToCopy );

		if ( pParametersInput[endMarker] != PSX_NULL )
			*pMarker = endMarker + 1;
		else
			*pMarker = endMarker;

		return TRUE;
	}

	Tokenizer2::Tokenizer2( const CHAR *pParameters )
		: m_pParamInput( pParameters ), m_marker( 0 )
	{

	}

	void Tokenizer2::AddSeparator( const CHAR separator )
	{
		m_separators.PushBack( separator );
	}

	void Tokenizer2::ClearSeparators( void )
	{
		m_separators.Clear();
	}

	void Tokenizer2::SetNewInpuParameters( const CHAR *pParameters )
	{
		m_pParamInput = pParameters;
		m_marker = 0;
	}

	BOOL Tokenizer2::NextToken( String *pTokenToStore ) 
	{
		if ( m_pParamInput == PSX_NULL || pTokenToStore == PSX_NULL )
			return FALSE;

		// The rule is that we stop everytime we hit a null.
		// If we hit at the start, that means its the end
		// If we started with something valid then ended with one of the terminations, we have a valid token.

		CHAR currentChar = m_pParamInput[m_marker];

		if ( currentChar  == PSX_NULL )
			return FALSE;

		UPOS_T startMarker = m_marker;
		UPOS_T endMarker = m_marker;

		// We want to skip any inital separators or null and set the startMarker from there
		while ( currentChar != PSX_NULL )
		{
			BOOL bContinue = FALSE;

			// Compare it against the list of separators
			for ( SIZE_T i = 0; i < m_separators.GetSize(); ++i )
			{
				if ( currentChar == m_separators[i] )
				{
					bContinue = TRUE;
					break;
				}
			}

			if ( bContinue )
			{
				++startMarker;
				currentChar = m_pParamInput[startMarker];
				continue;
			}
			else
			{
				break;
			}
		}

		endMarker = startMarker;

		while ( currentChar != PSX_NULL )
		{
			BOOL bBreak = FALSE;

			// Compare it against the list of separators
			for ( SIZE_T i = 0; i < m_separators.GetSize(); ++i )
			{
				if ( currentChar == m_separators[i] )
				{
					bBreak = TRUE;
					break;
				}
			}

			if ( bBreak == TRUE )
			{
				break;
			}

			++endMarker;
			currentChar = m_pParamInput[endMarker];
		}

		if ( startMarker == endMarker )
			return FALSE;

		// Create new token
		SIZE_T numToCopy = (endMarker - startMarker);
		pTokenToStore->Copy( &m_pParamInput[startMarker], numToCopy );

		if ( m_pParamInput[endMarker] != PSX_NULL )
			m_marker = endMarker + 1;
		else
			m_marker = endMarker;

		return TRUE;
	}


}